package org.elanfox.cloud.mybatis.ddl.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.elanfox.cloud.mybatis.ddl.dos.SchemaColumn;
import org.elanfox.cloud.mybatis.ddl.mapper.CreateMysqlTablesMapper;
import org.elanfox.cloud.mybatis.ddl.model.EntityColumn;
import org.elanfox.cloud.mybatis.ddl.model.EntityTable;
import org.elanfox.cloud.mybatis.ddl.service.SqlDDLService;
import org.elanfox.cloud.mybatis.utils.EntityHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @author allan
 * @version 1.0.0
 * @date 2021/4/20
 */
@Service("mySqlDDLService")
@Slf4j
public class MySqlDDLServiceImpl implements SqlDDLService {
    @Autowired
    private CreateMysqlTablesMapper mysqlTablesMapper;

    @Override
    public void create() {
        Map<Class<?>, EntityTable> entityTableMap = EntityHelper.getEntityTables();

        for (Map.Entry<Class<?>, EntityTable> entry : entityTableMap.entrySet()) {
            EntityTable entityTable = entry.getValue();
            if (mysqlTablesMapper.countByTableName(entityTable.getName()) > 0) {
                continue;
            }
            log.info("Creating table " + entityTable.getName());
            mysqlTablesMapper.createTable(entityTable);
        }
    }

    @Override
    public void dropAndCreate() {
        Map<Class<?>, EntityTable> entityTableMap = EntityHelper.getEntityTables();
        for (Map.Entry<Class<?>, EntityTable> entry : entityTableMap.entrySet()) {
            EntityTable entityTable = entry.getValue();
            log.info("Dropping table " + entityTable.getName());
            mysqlTablesMapper.dropTable(entityTable.getName());
            log.info("Creating table " + entityTable.getName());
            mysqlTablesMapper.createTable(entityTable);
        }
    }

    @Override
    public void update() {
        Map<Class<?>, EntityTable> entityTableMap = EntityHelper.getEntityTables();

        for (Map.Entry<Class<?>, EntityTable> entry : entityTableMap.entrySet()) {
            EntityTable entityTable = entry.getValue();
            if (mysqlTablesMapper.countByTableName(entityTable.getName()) > 0) {
                log.info("Updating table " + entityTable.getName());
                List<SchemaColumn> columns = mysqlTablesMapper.findColumnsByTableName(entityTable.getName());

                for (EntityColumn entityColumn : entityTable.getEntityColumns()) {
                    SchemaColumn column = columns.stream()
                            .filter(p -> p.getColumn_name().equals(entityColumn.getName()))
                            .findFirst().orElse(null);

                    if (column == null) {
                        //添加列
                        mysqlTablesMapper.addColumn(entityTable.getName(), entityColumn);
                    } else {
                        if (!entityColumn.isEqualsToSchemaColumn(column)) {
                            //修改
                            mysqlTablesMapper.modifyColumn(entityTable.getName(), entityColumn);
                        }
                    }
                }

                //查看是否有要删除的列
//                for (SchemaColumn column : columns) {
//                    if (entityTable.getEntityColumns().stream().noneMatch(p -> p.getName().equals(column.getColumn_name()))) {
//                        mysqlTablesMapper.removeColumn(entityTable.getName(), column.getColumn_name());
//                    }
//                }
            } else {
                log.info("Creating table " + entityTable.getName());
                mysqlTablesMapper.createTable(entityTable);
            }
        }
    }

    @Override
    public void validate() {
        Map<Class<?>, EntityTable> entityTableMap = EntityHelper.getEntityTables();

        for (Map.Entry<Class<?>, EntityTable> entry : entityTableMap.entrySet()) {
            EntityTable entityTable = entry.getValue();
            log.info("Validating table " + entityTable.getName());
            if (mysqlTablesMapper.countByTableName(entityTable.getName()) == 0) {
                throw new RuntimeException("Table " + entityTable.getName() + " not exist");
            }
            List<SchemaColumn> columns = mysqlTablesMapper.findColumnsByTableName(entityTable.getName());
            for (EntityColumn entityColumn : entityTable.getEntityColumns()) {
                SchemaColumn column = columns.stream()
                        .filter(p -> p.getColumn_name().equals(entityColumn.getName()))
                        .findFirst().orElse(null);
                if (column == null) {
                    throw new RuntimeException("Column " + entityColumn.getName() + " is not exist in table " + entityTable.getName());
                }
                if (!entityColumn.isEqualsToSchemaColumn(column)) {
                    throw new RuntimeException("Column " + entityColumn.getName() + " is not same in table " + entityTable.getName());
                }
            }
        }
    }
}
